/*
 * Copyright (c) 2022，公司名称
 * All rights reserved.
 * 文件名称：high_uart.c
 * 摘要：高边串口
 * 当前版本：V1.0.0,WCD,2023/1/10,初版
 * 历史版本：Vx.x.x，编写者/修改者，修改时间，修改内容（重大发布时，总结重点变更内容）
 */

#include "high_includes.h"
/*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓应用层数据定义开始↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/
#if 1
static EM_TRUE_FALSE curr_init_status = FALSE;
static uint16_t current_init = 0u;
static uint16_t ADC0_SampleCount;           /* 采样计数 */
low_ADC_ORIG_DATA_struct low_ADC_OrgiData;  /* ADC 采样原始数据 */
high_ADC_ORIG_DATA_struct high_ADC_OrgiData; /* ADC 采样原始数据 */
static uint16_t ADC0_BUFF[ADC0_BUFF_NUM][ADC0_BUFF_LEN];
static uint16_t ADC0_CompleteFlag;   /* 1:一个采集序列完成 */
  static uint8_t Number_of_AD_channels = 3; //AD软件触发三通道 or 四通道
void high_AnalSiglPro_CalculSum(void);
#endif
/*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑应用层数据定义结束↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/
#define WATERMARK_VALUE (9U)
void Three_channelADC_init(channel_ADC channel);
typedef struct
{
  PORT_ID_t PORT;
  /*!< Configure ADC differential mode
      - ADC_SINGLE_MODE (0): ADC single mode
      - ADC_DIFF_MODE (1): ADC differential mode */

  PORT_GPIONO_t GPIO;
  /*!< Configure ADC positive channel
      - ADC_P_CH0 (0):   ADC Positive channel 0
      - ......
      - ADC_P_CH20 (20): ADC Positive channel 20 */

  PORT_PinMuxFunc_t PT;
  /*!< Configure ADC negtive channel
      - ADC_N_CH0 (0):   ADC Negtive channel 0
      - ADC_N_CH1 (1):   ADC Negtive channel 1
      - ADC_N_CH2 (2):   ADC Negtive channel 2
      - ADC_N_VSS (3):   ADC Negtive connected with VSS
   */
} PORT_ADC_Config_t;

/* Sample result with channel information */
static uint32_t adcResult[WATERMARK_VALUE + 1] = {0};
/*Sample data value */
static uint16_t dataResult[WATERMARK_VALUE + 1] = {0};
/*Sample channel value */
static uint16_t chResult[WATERMARK_VALUE + 1] = {0};


/*Sample result with channel information */
static uint32_t adcswResult[4][WATERMARK_VALUE + 1] = {0};
/*Sample data value */
static volatile uint16_t dataswResult[4][WATERMARK_VALUE + 1] = {0};
/*Sample channel value */
static volatile uint16_t chswResult[4][WATERMARK_VALUE + 1] = {0};
static channel_ADC channel = ADC_CH1;
static uint8_t Adc_Sw_Int_Flag = 0;
ADC_Config_t adcCfg =
    {
        ADC_RESOLUTION_12BIT,  /* ADC 12-bit resolution */
        ADC_VREF_INTERNAL,     /* Internal Vref_H to 5V, Vref_L to 0V reference */
        ADC_NORMAL_SW_TRIGGER, /* Software trigger select */
        ADC_CONVERSION_SINGLE, /* ADC single conversion */
        ADC_AVGS_8,            /* 8 times average for each conversion*/
        200                    /* Set the time interval between two samples when average is enabled or
                      in continues mode. Please refer to STS definition in RM to see the constraint */
};
ADC_ChannelConfig_t adcswChannelCfg[4] =
    {
        {
            ADC_SINGLE_MODE, /* Single-Ended Mode Selected */
            ADC_P_CH1,       /* Single mode, channel[7] and vssa */
            ADC_N_NONE,      /* Single mode, N-channel donn't need to configure */
        },
        {
            ADC_SINGLE_MODE, /* Single-Ended Mode Selected */
            ADC_P_CH5,       /* Single mode, channel[7] and vssa */
            ADC_N_NONE,      /* Single mode, N-channel donn't need to configure */
        },
        {
            ADC_SINGLE_MODE, /* Single-Ended Mode Selected */
            ADC_P_CH3,       /* Single mode, channel[7] and vssa */
            ADC_N_NONE,      /* Single mode, N-channel donn't need to configure */
        },
				{
						ADC_SINGLE_MODE, /* Single-Ended Mode Selected */
            ADC_P_CH9,       /* Single mode, channel[7] and vssa */
            ADC_N_NONE,      /* Single mode, N-channel donn't need to configure */
				}
		};
PORT_ADC_Config_t port_adc[4] =
    {
        // PORT_A GPIO_1 PTA1_ADC0_CH1
        {
            PORT_A,        /* Single-Ended Mode Selected */
            GPIO_1,        /* Single mode, channel[7] and vssa */
            PTA1_ADC0_CH1, /* Single mode, N-channel donn't need to configure */
        },
				{
            PORT_B,        /* Single-Ended Mode Selected */
            GPIO_1,        /* Single mode, channel[7] and vssa */
            PTB1_ADC0_CH5, /* Single mode, N-channel donn't need to configure */
        },
        {
            PORT_A,        /* Single-Ended Mode Selected */
            GPIO_7,        /* Single mode, channel[7] and vssa */
            PTA7_ADC0_CH3, /* Single mode, N-channel donn't need to configure */
        },    
				{
						PORT_C,
						GPIO_1,
						PTC1_ADC0_CH9
				}
		};
ADC_Config_t subcaseAdcCfg =
    {
        ADC_RESOLUTION_12BIT,  /* ADC 12-bit resolution */
        ADC_VREF_INTERNAL,     /* Internal Vref_H to 5V, Vref_L to 0V reference 内部Vref_H至5V，Vref_L至0V参考*/
        ADC_TDG_TRIGGER,       /* TDG trigger select TDG触发器选择*/
        ADC_CONVERSION_SINGLE, /* ADC single conversion ADC单次转换*/
        ADC_AVGS_8,            /* 8 times average for each conversion每次转换的平均值为8倍*/
        100,                   /* Set the time interval between two samples when average is enabled or
                      in continues mode. Please refer to STS definition in RM to see the constraint */
};

ADC_ChannelConfig_t adcChannelCfg =
    {
        ADC_SINGLE_MODE, /* Single-Ended Mode Selected 已选择单端模式*/
        ADC_P_CH9,       /* Single mode, channel[7] and vssa 单模、通道[7]和vssa*/
        ADC_N_NONE,      /* Single mode, N-channel donn't need to configure 单模，N通道无需配置*/
};

ADC_TDGTriggerConfig_t adcTriggerConfig =
    {
        ADC_LOOP_MODE, /* Loop mode Selected 已选择循环模式*/
        ADC_P_CH9,     /* CMD0: channel 7; */
        ADC_P_CH9,     /* CMD1: channel 7; */
        ADC_P_CH9,     /* CMD2: channel 7; */
        ADC_P_CH9,     /* CMD3: channel 7; */
        ADC_P_CH9,     /* CMD4: channel 7; */
        ADC_P_CH9,     /* CMD5: channel 7; all CMDs can be configured as different channels */
};

/* mod value, single, divide1, HW trig, clear to modulator mod值，单个，分频1，HW触发，清除到调制器*/
TDG_InitConfig_t config =
    {
        0x9c40, TDG_COUNT_SINGLE, TDG_CLK_DIVIDE_8, TDG_TRIG_EXTERNAL, TDG_UPDATE_IMMEDIATELY, TDG_CLEAR_DELAY};

TDG_DelayOutputConfig_t doConfig[1] =
    {
        {TDG_DO_0, 0X1388, ENABLE},
};

const TDG_ChannelConfig_t chConfig =
    {
        TDG_CHANNEL_0, 0x16, 1, doConfig};
void adc_sw_tcomp_cb(void)
{
	if(NO == ADC0_CompleteFlag)
	{
		/*Get sample result, suggest to discard the first sampled data due to the instability of it*/
		for(uint8_t i = 0; i<10;i++)
		{
			adcswResult[channel][i] = ADC_GetConversionResult(ADC0_ID);
			dataswResult[channel][i] = adcswResult[channel][i] & 0xfff;
			chswResult[channel][i] = (adcswResult[channel][i] >> 12) & 0x1f;
			ADC0_BUFF[channel][i] =  dataswResult[channel][i];
		}
		/* 累积采样次数，如果满足采样次数，终止采样，标记采样完成 */
    ++ADC0_SampleCount;
		if(ADC0_SampleCount >= Number_of_AD_channels)
		{
			ADC0_SampleCount = 0;       /* 清通道计数器 */
			ADC0_CompleteFlag = 1;      /* 标记采样完成 */
		}
	}
	ADC_IntClear(ADC0_ID, ADC_TCOMP_INT);
}

void ADC_FifoWaterMakerIntCallback()
{
  uint32_t i = 0;
  /*Get sample result, suggest to discard the first sampled data due to the instability of it
  获取采样结果，由于第一个采样数据不稳定，建议丢弃该数据*/
  /* toggle output value */
  for (i = 0; i < (WATERMARK_VALUE + 1); i++)
  {
    adcResult[i] = ADC_GetConversionResult(ADC0_ID);
    dataResult[i] = adcResult[i] & 0xfff;
		current_init = current_init + dataResult[i];
    chResult[i] = (adcResult[i] >> 12) & 0x1f;
		ADC0_BUFF[ADC_CH9][i] =  dataResult[i];
  }
  if (TRUE != curr_init_status)
  {
		current_init = (current_init/10);
		if( current_init >= 50)
		{
			 current_init = 0;
		}else{}
    curr_init_status = TRUE;
  }else{}
  
  ADC_IntClear(ADC0_ID, ADC_FWM_INT);
}
void ADC_TCOMPMakerIntCallback()
{
  // GPIO_TogglePinOutput(PORT_C, GPIO_8);
  ADC_IntClear(ADC0_ID, ADC_TCOMP_INT);
}
void TDG_IntCallback()
{
  /* toggle output value */
  // GPIO_TogglePinOutput(PORT_C, GPIO_9);
  TDG_IntClear(TDG0_ID, TDG_INT_CH0);
}

void high_adc_pwm_clock_init()
{
  /*TMU enable*/
  SYSCTRL_EnableModule(SYSCTRL_TMU);

  /* Select clock source for TDG */
  CLK_ModuleSrc(CLK_TDG0, CLK_SRC_FIRC64M);
  CLK_SetClkDivider(CLK_TDG0, CLK_DIV_2); // CLK_DIV_1
  /*Enable TDG module */
  SYSCTRL_EnableModule(SYSCTRL_TDG0);

  /* Select clock source for ADC. Selection of ADC functional clock is suggested to be the same with bus clock*/
  CLK_ModuleSrc(CLK_ADC0, CLK_SRC_FIRC64M);
  /*set clock for ADC , make sure it is not greater than bus clock*/
  CLK_SetClkDivider(CLK_ADC0, CLK_DIV_1);
  /* Reset ADC */
  SYSCTRL_ResetModule(SYSCTRL_ADC0);
  /* Enable ADC module */
  SYSCTRL_EnableModule(SYSCTRL_ADC0);
}
void high_adc_pwm_init(void)
{
  TMU_SetUnlockForModule(TMU_MODULE_TDG0_TRIG_IN);                      // 解锁TMU目标模块的相关寄存器，则寄存器可写。
  TMU_SetSourceForModule(TMU_SOURCE_TIM0_CH0, TMU_MODULE_TDG0_TRIG_IN); // 为TMU目标模块设置源。
  TMU_ModuleCmd(TMU_MODULE_TDG0_TRIG_IN, ENABLE);                       // 启用/禁用TMU模块中的目标模块。

  /* Register the callback function */
  ADC_InstallCallBackFunc(ADC0_ID, ADC_FWM_INT, ADC_FifoWaterMakerIntCallback);
  ADC_InstallCallBackFunc(ADC0_ID, ADC_TCOMP_INT, ADC_TCOMPMakerIntCallback);
  /* Reset software */
  ADC_SoftwareReset(ADC0_ID);
  /* Initialize ADC */
  ADC_Init(ADC0_ID, &subcaseAdcCfg);
  /*Configure the FIFO depth*/
  ADC_FifoDepthRedefine(ADC0_ID, 16);
  /* Set ADC watermark*/
  ADC_FifoWatermarkConfig(ADC0_ID, 5);
  /* Configure input channel*/
  ADC_ChannelConfig(ADC0_ID, &adcChannelCfg);
  /* unmask FIFO watermark interrupt */
  ADC_IntMask(ADC0_ID, ADC_INT_ALL, MASK);
  ADC_IntMask(ADC0_ID, ADC_FWM_INT, UNMASK);
  ADC_IntMask(ADC0_ID, ADC_TCOMP_INT, UNMASK);
  /* Set trigger mode 设置触发模式*/
  ADC_TDGTriggerConfig(ADC0_ID, &adcTriggerConfig);
  /* Clear FWM interrupt */
  ADC_IntClear(ADC0_ID, ADC_FWM_INT);
  ADC_IntClear(ADC0_ID, ADC_TCOMP_INT);
  /* Enable ADC module */
  ADC_Enable(ADC0_ID);
  /* Enable ADC interrupt */
  NVIC_EnableIRQ(ADC0_IRQn);

  /* Initialize TDG */
  TDG_InitConfig(TDG0_ID, &config);
  /* Set TDG delay output*/
  TDG_ChannelDelayOutputConfig(TDG0_ID, &chConfig, ENABLE);
  /* enable TDG */
  TDG_Enable(TDG0_ID, ENABLE);
  /* Load channel configuration 加载通道配置*/
  TDG_LoadCmd(TDG0_ID);

  TDG_InstallCallBackFunc(TDG0_ID, TDG_INT_CH0, TDG_IntCallback);
  TDG_IntMask(TDG0_ID, TDG_INT_CH0, UNMASK);
  TDG_IntClear(TDG0_ID, TDG_INT_CH0);
  NVIC_EnableIRQ(TDG0_IRQn);
}

void Three_channelADC_init(channel_ADC channel)
{
  /* Reset ADC */
  SYSCTRL_ResetModule(SYSCTRL_ADC0);
  /* Enable ADC clock */
  SYSCTRL_EnableModule(SYSCTRL_ADC0);

  /* Reset software */
  ADC_SoftwareReset(ADC0_ID);
  /* Initialize ADC */
  ADC_Init(ADC0_ID, &adcCfg);
	/*Configure the FIFO depth*/
  ADC_FifoDepthRedefine(ADC0_ID, 16);
  /* Set ADC watermark*/
  ADC_FifoWatermarkConfig(ADC0_ID, 10);
  SYSCTRL_EnableModule(SYSCTRL_PORTA);
  PORT_PinmuxConfig(port_adc[channel].PORT, port_adc[channel].GPIO, port_adc[channel].PT);
  /* Channel configurate */
  ADC_ChannelConfig(ADC0_ID, &adcswChannelCfg[channel]); //!!

  /* Only unmask TCOMP interrupt */
  ADC_IntMask(ADC0_ID, ADC_INT_ALL, MASK);
  ADC_IntMask(ADC0_ID, ADC_FWM_INT, UNMASK);
  /* Clear TCOMP interrupt */
  ADC_IntClear(ADC0_ID, ADC_FWM_INT);
  /* Enable ADC */
  ADC_Enable(ADC0_ID);
  /* Enable ADC interrupt */
  NVIC_EnableIRQ(ADC0_IRQn);
}
void high_adc_sw_clock_init(void)
{
  /* Select clock source for ADC. Selection of ADC functional clock is suggested to be the same with bus clock*/
  CLK_ModuleSrc(CLK_ADC0, CLK_SRC_FIRC64M);
  /*set clock for ADC , make sure it is not greater than bus clock*/
  CLK_SetClkDivider(CLK_ADC0, CLK_DIV_2);

  /* Reset ADC */
  SYSCTRL_ResetModule(SYSCTRL_ADC0);
  /* Enable ADC clock */
  SYSCTRL_EnableModule(SYSCTRL_ADC0);
  /* Select clock source for PORTB and enable */
  CLK_ModuleSrc(CLK_PORTB, CLK_SRC_FIRC64M);
  SYSCTRL_EnableModule(SYSCTRL_PORTB);
  /* Configure PTB3 as adc channel7  */
  PORT_PinmuxConfig(PORT_B, GPIO_3, PTB3_ADC0_CH7);
}

void high_adc_sw_init(void)
{
  /* Register the callback function */
  ADC_InstallCallBackFunc(ADC0_ID, ADC_FWM_INT, adc_sw_tcomp_cb);
  /* Reset software */
  ADC_SoftwareReset(ADC0_ID);
  /* Initialize ADC */
  ADC_Init(ADC0_ID, &adcCfg);
	/*Configure the FIFO depth*/
  ADC_FifoDepthRedefine(ADC0_ID, 16);
  /* Set ADC watermark*/
  ADC_FifoWatermarkConfig(ADC0_ID, 10);
  /* Channel configurate */
  ADC_ChannelConfig(ADC0_ID, &adcswChannelCfg[0]);
  /* Only unmask TCOMP interrupt */
  ADC_IntMask(ADC0_ID, ADC_INT_ALL, MASK);
  ADC_IntMask(ADC0_ID, ADC_FWM_INT, UNMASK);
  /* Clear TCOMP interrupt */
  ADC_IntClear(ADC0_ID, ADC_FWM_INT);
  /* Enable ADC */
  ADC_Enable(ADC0_ID);
  /* Enable ADC interrupt */
  NVIC_EnableIRQ(ADC0_IRQn);
  //ADC_SoftwareTrigger(ADC0_ID);
}
void ADC5ms_trigger_switching()
{
  static uint8_t ADC_mode_switching = 0; // 1:切换为SW触发ADC，2：PWM触发ADC
  static uint8_t SWADC_flag = 0;         // 1:SW软件切换，0：PWM触发ADC
  static uint32_t receive_timer1ms = 0;  // 1ms计数器
	static uint8_t  Trigger_Counter  = 0;  //	ADC每个通道触发10次采样计数器
  if (PTC_MODE_OFF == high_side_st.ptc_mode_st)
  {
    Number_of_AD_channels = 4;
  }else{Number_of_AD_channels = 3;}
  
  if (Get1MsTickInterval(receive_timer1ms, 5) == YES)
  {
    ADC_mode_switching++;
    receive_timer1ms = Get1MsTickVal();
    if (1 == ADC_mode_switching)
    {
      high_adc_sw_clock_init();
      high_adc_sw_init(); // adc sw 初始化
      SWADC_flag = 1;
    }
    else if (2 == ADC_mode_switching)
    {
      high_adc_pwm_clock_init();
      high_adc_pwm_init(); // adc pwm 初始化
      ADC_mode_switching = 0;
      SWADC_flag = 0;
    }
    else
    {
    }
  }
  else
  {
    if (1 == SWADC_flag && NO == ADC0_CompleteFlag)
    {
			ADC_SoftwareTrigger(ADC0_ID);
			Trigger_Counter++;
			if(10 < Trigger_Counter) //每个通道采样十次后切换通道
			{
				channel++;
				if (channel == Number_of_AD_channels)
				{
					channel = ADC_CH1;
				}
				Three_channelADC_init(channel);
			}
    }
    else
    {
    }
  }
	high_AnalSiglPro_CalculSum();//模拟信号处理 计算初始化采样信号的和值和最值
}

/*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓应用层函数定义开始↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/
#if 1
/*
**********************************************************
*name: AnalSiglPro_CalculSum
*descripiton: 模拟信号处理 计算初始化采样信号的和值和最值
**********************************************************
*/
EM_TRUE_FALSE adc_get_curr_status(void)
{
   return  curr_init_status;
}
uint16_t adc_get_curr_init(void)
{
    return current_init;
}
void high_AnalSiglPro_CalculSum(void)
{
#define HIGH_SUMDATANUM (sizeof(high_ADC_ORIG_DATA_struct) / sizeof(ADC_ORIG_DATA_TYPE_DEF)) /*数据个数 */

#define GET_MAX(max, a, d)           \
  {                                  \
    (max) = ((a) > (d)) ? (a) : (d); \
  }
#define GET_MiM(min, a, d)           \
  {                                  \
    (min) = ((a) < (d)) ? (a) : (d); \
  }

  ADC_ORIG_DATA_TYPE_DEF *ptr = &(high_ADC_OrgiData.V15);
  uint32_t sum[HIGH_SUMDATANUM];
  uint16_t max[HIGH_SUMDATANUM];
  uint16_t min[HIGH_SUMDATANUM];
  uint16_t i, j;
  uint16_t tmp;

  /* 如果正在采样，退出 */
  if (NO == ADC0_CompleteFlag)
  {
    ;
    ;
    ;
  }
  else
  {
    /* 初始化缓存区 */
    for (i = 0; i < HIGH_SUMDATANUM; i++)
    {
      sum[i] = 0;
      max[i] = 0;
      min[i] = 0xffff;
    }

    /*累计求和，求最大值，求最小值 */
    for (i = 0; i < HIGH_ADC0_BUFF_LEN; i++)
    {
      for (j = 0; j < HIGH_SUMDATANUM; j++)
      {
        (ptr + j)->wave[i] = ADC0_BUFF[j][i]; /* 记录原始数据 */
        sum[j] += (ptr + j)->wave[i];         /* 累和 */

        tmp = max[j];
        GET_MAX(max[j], tmp, (ptr + j)->wave[i]); /* 求最大值 */
        tmp = min[j];
        GET_MiM(min[j], tmp, (ptr + j)->wave[i]); /* 求最小值 */
      }
    }

    /*更新数据 */
    for (j = 0; j < HIGH_SUMDATANUM; j++)
    {
      (ptr + j)->sum = (uint16_t)sum[j];
      (ptr + j)->max = max[j];

      (ptr + j)->min = min[j];

      (ptr + j)->avg =
          ((ptr + j)->sum - (ptr + j)->max - (ptr + j)->min) / (ADC0_BUFF_LEN - 2u);
    }

    ADC0_CompleteFlag = NO; /* 清 采样完成标志 */
    //ADC0_Start();           /* 启动 ADC 采样 */
                            //        DBG_ADC_PRINT_ORGI_DATA();                                              /* 调试 打印 采样信息*/
  }
}
uint32_t get_current_ADC_value(void)
{
  uint32_t current_ADC = 0;
  for (uint8_t i = 0; i < 10; i++)
  {
    current_ADC = current_ADC + adcResult[i];
  }
  current_ADC = current_ADC/10;
  return current_ADC;
}
#endif
/*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑应用层函数定义结束↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/